// FinanceView.cpp : implementation of the CFinanceView class
//

#include "stdafx.h"
#include "Finance.h"

#include "financedef.h"
#include "CDataFile.h"

#include "FinanceDoc.h"
#include "FinanceView.h"
#include "BankView.h"
#include "SearchView.h"

#include "PageDateRange.h"
#include "PageLoginInfo.h"
#include "PageBakRestore.h"
#include "DlgAddNew.h"
#include "DlgModify.h"
#include "DlgSearch.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


extern CFinanceApp theApp;       

// global var for list view
PTLVCOL		g_myColumn[ACCOUNT_COLUMNS] = 
					{	// the array order is same as ORDERCOLUMN define
						{ "Date",				LVCFMT_CENTER,  85,	1, 3 },	// 0
						{ "Amount",				LVCFMT_LEFT,   100,	1, 0 },	// 1
						{ "Purpose",			LVCFMT_LEFT,   115,	1, 2 },	// 2
						{ "Flow of accounts",	LVCFMT_CENTER, 118,	0, 0 },	// 3
						{ "Owner",				LVCFMT_CENTER,  95,	1, 1 },	// 18
						{ "Comment",			LVCFMT_LEFT,   260, 1, 4 }	// 19
					};


// 
// Get system default language
// default is GB
//---------------------------------------------------------------------------
INT		wtkGetSysLanguage( void )
{
	LANGID		retLan; 
	WORD		subLan;
	
	retLan = GetSystemDefaultLangID();		
	if( PRIMARYLANGID( retLan ) == LANG_CHINESE )
	{
		subLan = SUBLANGID( retLan );
		switch( subLan ) 
		{
		case SUBLANG_CHINESE_TRADITIONAL:
		case SUBLANG_CHINESE_HONGKONG:
		case SUBLANG_CHINESE_MACAU:
		case SUBLANG_CHINESE_SINGAPORE:
			return WTK_BIG5;
			
		case SUBLANG_CHINESE_SIMPLIFIED:
			return WTK_GB;
			
		default :
			return WTK_GB; // gb
		}
	}
	else
	{
		return WTK_GB;     // gb
	}
}


// 
// Must be check CsTime string first, maybe "9/5/2002" form
// And ensure "Year/Month/Date" formats
// convert "2005/7/9"(or "2005-07-09" ) to CTime format
//---------------------------------------------------------------------------
CTime	DTString2CTime( CString &CsTime )
{
	CString			csSQL;
	CHAR			chTmp[56] = { 0 };
	INT				i, iYear, iMonth, iDay;
	
	
	// <> check format first
	i = CsTime.FindOneOf( "/-" );
	if( i<4 )
	{
		// means "M/D/Year", must convert
		strcpy( chTmp, CsTime.Right( 4 ) );
		iYear = atoi( chTmp );
		
		strcpy( chTmp, CsTime.Left( i ) );
		iMonth = atoi( chTmp );
		
		if( CsTime[i] == '/' )
			iDay = CsTime.ReverseFind( '/' );
		else
			iDay = CsTime.ReverseFind( '-' );

		strcpy( chTmp, CsTime.Mid( i + 1, iDay - i - 1 ) );
		iDay = atoi( chTmp );
	}
	else
	{
		strcpy( chTmp, CsTime ); // "2005/7/9" or "2005/12/31"

		iYear = atoi( chTmp );
		
		if( CsTime[6] == '/' || CsTime[6] == '-' ) 
		{
			strcpy( chTmp, "0" );
			csSQL = CsTime.Mid( 5, 1 );
			strcat( chTmp, csSQL );
		}
		else
		{
			csSQL = CsTime.Mid( 5, 2 );
			strcpy( chTmp, csSQL );
		}
		iMonth = atoi( chTmp );
		
		memset( chTmp, 0, sizeof(chTmp) );
		if( CsTime[6] == '/' || CsTime[6] == '-' ) 
		{
			strcpy( chTmp, "0" );
			csSQL = CsTime.Mid( 7, 2 );
			strcat( chTmp, csSQL );
		}
		else
		{
			csSQL = CsTime.Mid( 8, 2 );
			strcpy( chTmp, csSQL );
		}
		iDay = atoi( chTmp );
	}
	
	CTime 	tmRec( iYear, iMonth, iDay, 0, 0, 0 );
	
	return tmRec;
}


/////////////////////////////////////////////////////////////////////////////
// CFinanceView

IMPLEMENT_DYNCREATE(CFinanceView, CListEditView)

BEGIN_MESSAGE_MAP(CFinanceView, CListEditView)
	//{{AFX_MSG_MAP(CFinanceView)
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
	ON_NOTIFY_REFLECT(NM_CLICK, OnClickList)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclkList)
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclickList)
	ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeyDownList)
	ON_WM_CREATE()
	ON_COMMAND(ID_REFRESH, OnRefresh)
	ON_COMMAND(ID_ADDNEW, OnAddnew)
	ON_COMMAND(ID_MODIFY, OnModify)
	ON_UPDATE_COMMAND_UI(ID_MODIFY, OnUpdateModify)
	ON_COMMAND(ID_DELEONE, OnDeleone)
	ON_UPDATE_COMMAND_UI(ID_DELEONE, OnUpdateDeleone)
	ON_COMMAND(ID_SETUP, OnSetup)
	ON_BN_CLICKED(ID_SEARCH, OnSearch)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CListEditView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CListEditView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CListEditView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFinanceView construction/destruction

CFinanceView::CFinanceView()
{
	m_iLstCurSel  = -1;
	m_ordercolumn = date;
	m_disporder	  = desc;
}

CFinanceView::~CFinanceView()
{
	if( m_pRecordset != NULL )
	{
		if( m_pRecordset->State )
			m_pRecordset->Close();
		m_pRecordset = NULL;
	}

	if( m_pBankbookset != NULL )
	{
		if( m_pBankbookset->State )
			m_pBankbookset->Close();
		m_pBankbookset = NULL;
	}
}

BOOL CFinanceView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
	
	cs.style |= LVS_REPORT |
				LVS_SINGLESEL |
				LVS_SHOWSELALWAYS; 
				//LVS_OWNERDRAWFIXED;
	
	return CListView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CFinanceView drawing

void CFinanceView::OnDraw(CDC* pDC)
{
	CFinanceDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

//
//------------------------------------------------------------
void CFinanceView::OnInitialUpdate()
{
	CListEditView::OnInitialUpdate();

	// Gain a reference to the list control itself
	CListCtrl&		InnerLst = GetListCtrl();
	HDITEM			hditem;
	CFont			m_font;
	INT				i, j;
	

	m_imagelist.Create(IDB_HEADER, 9, 1, RGB(255,255,255));
	m_bitmap.LoadBitmap(IDB_BITMAP);
	
	CFlatHeaderCtrl* pFlatHeader = (CFlatHeaderCtrl*)InnerLst.GetHeaderCtrl();
	pFlatHeader->ModifyProperty(FH_PROPERTY_STATICBORDER, TRUE);
	pFlatHeader->SetImageList(&m_imagelist);
	

	for( j=0,i=0; i<ACCOUNT_COLUMNS; i++ )
	{
		InnerLst.InsertColumn( j,	g_myColumn[i].chName, 
									g_myColumn[i].iFormat, 
									g_myColumn[i].iWidth );
		if( 1 == g_myColumn[i].btImgFlag ) 
		{
			hditem.mask = HDI_FORMAT|HDI_IMAGE;	//|HDI_BITMAP;	
			pFlatHeader->GetItem( j, &hditem );
			hditem.fmt |= HDF_IMAGE;			//|HDF_BITMAP;
			hditem.iImage = g_myColumn[i].btmgIdx;
			hditem.hbm = (HBITMAP)m_bitmap;
			pFlatHeader->SetItem( j, &hditem );
		}
		j++;
	}
	
	m_font.CreateFont(16, 0,0,0,FW_NORMAL, 0,0,0,
		DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
		DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
	InnerLst.SetFont(&m_font);
	
	// <> Init list ctrl
	InnerLst.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT);
	InnerLst.SetBkColor(RGB(252,250,244)); //(RGB(244,242,220)),RGB(247,247,255)
	//InnerLst.SetTextColor(RGB(0,0,255));
	InnerLst.SetTextBkColor(RGB(252,250,244));
	
	HDITEMEX hditemex;
	hditemex.iMinWidth = 21;
	hditemex.iMaxWidth = 200;
	pFlatHeader->SetItemEx(1, &hditemex);
	
	// <> Open RecordSet
	m_pRecordset.CreateInstance(__uuidof(Recordset));
	m_pBankbookset.CreateInstance(__uuidof(Recordset));
	

	// <> Refresh
	OnRefresh();
}

/////////////////////////////////////////////////////////////////////////////
// CFinanceView printing

BOOL CFinanceView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CFinanceView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CFinanceView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CFinanceView diagnostics

#ifdef _DEBUG
void CFinanceView::AssertValid() const
{
	CListView::AssertValid();
}

void CFinanceView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}

CFinanceDoc* CFinanceView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFinanceDoc)));
	return (CFinanceDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFinanceView message handlers

//
//------------------------------------------------------------
void CFinanceView::ShowAccountRec(LONG lAbsIdx)
{
	INT				i, j, iItem;
	LONG			lItemIdx;
	_variant_t		var;
	CString			csItem[2];
	CListCtrl&		InnerLst = GetListCtrl();
	// fields name of account table
	CHAR			*chAccount[] = {
									"Date",
									"Amount",
									"Purpose",
									"FlowClass",
									"Owner",
									"Comment"									
								};
	
	
	//<> reset state
	InnerLst.DeleteAllItems();
	m_iLstCurSel = -1;
	
	try
	{
		if(!m_pRecordset->BOF)
			m_pRecordset->MoveFirst();
		else
		{
			//AfxMessageBox("Table is NULL");
			return;
		}
		
		iItem = 0;
		while(!m_pRecordset->adoEOF)
		{
			var = m_pRecordset->GetCollect("Index");	// LONG
			if(var.vt != VT_NULL)
				lItemIdx = (LONG)(var);	// !!! need check this convertion method !!!
			
			// <> It should optimize performance by double while{}
			//    by lAbsIdx ( -1 or not )
			// sync m_iLstCurSel after refresh
			if( lItemIdx == lAbsIdx ) 
				m_iLstCurSel = iItem;
			
			var = m_pRecordset->GetCollect( chAccount[0] );	// date
			if(var.vt != VT_NULL)
				csItem[0] = (LPCSTR)_bstr_t(var);
			else
				csItem[0].Empty();	
			
			InnerLst.InsertItem( iItem, csItem[0], 0 );	
			
			for( j=1,i=1; i<ACCOUNT_COLUMNS; i++ )
			{
				var = m_pRecordset->GetCollect( chAccount[i] );	
				if(var.vt != VT_NULL)
					csItem[1] = (LPCSTR)_bstr_t(var);
				else
					csItem[1].Empty();	// comment might be NULL in Table
				
				InnerLst.SetItemText( iItem, j++, csItem[1] );	
			}

			m_pRecordset->MoveNext();
			iItem++;
		}
		
		// <> Synchronize the table( Account )
		if( m_iLstCurSel >= 0 ) 
		{
			InnerLst.SetItemState( m_iLstCurSel, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED );
			
			m_pRecordset->MoveFirst();
			m_pRecordset->Move( long(m_iLstCurSel) );
		}
		
	}
	catch(_com_error *e)
	{
		AfxMessageBox(e->ErrorMessage());
	}
	
}

//
// open account by m_ordercolumn and m_disporder 
// and date range [ 2005/07/10 - 2005/08/09 ]
//------------------------------------------------------------
void CFinanceView::OpenAccount()
{
	CDataFile	MoneyDF( MONEY_CFG );
	_variant_t	var;
	INT			iRange = 1;
	CHAR	   *chRange[] = {
								"All",		// 0
								"Finance",	// 1
								"Month",	// 2
								"User"		// 3
							};
	CHAR		chSQL[256];
	CString		csSQL;
	CString		csBegDate, csEndDate;
	CTime		ctBegDate, ctEndDate;	
	CHAR		*chOrder[] = { "ASC", "DESC" };
	CHAR		*chColumn[] = {	// the array order is same as ORDERCOLUMN define
								"Amount ",
								"Purpose ",
								"FlowClass ",
								"Date ",			// date
								"Owner ",
								"Comment "
							};
	

	// <> date range type
	iRange = MoneyDF.GetInt( "range type", "Date range" );
	// <> Update Count info status bar 
	CStatusBar *pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
	sprintf( chSQL, " Date range : %s ", chRange[ iRange ] );
	pStatusBar->SetPaneText( 1, chSQL );
	
	// <> begin date and end date
	ctBegDate = MoneyDF.GetInt( "begindate", "Date range" );
	ctEndDate = MoneyDF.GetInt( "enddate", "Date range" );

	if( wtkGetSysLanguage() == WTK_BIG5 ) 
	{	// in Big5 system, is "2005/7/12"
		csBegDate = ctBegDate.Format( "%Y/%m/%d" );  
		csEndDate = ctEndDate.Format( "%Y/%m/%d" );
	}
	else
	{	// in GB system, is "2005-7-12"
		csBegDate = ctBegDate.Format( "%Y-%m-%d" );  
		csEndDate = ctEndDate.Format( "%Y-%m-%d" );
	}
	
	sprintf( chSQL, "SELECT * FROM Account WHERE Date >=#%s# AND Date <=#%s# ORDER BY ", csBegDate, csEndDate );
	csSQL = chSQL;
	csSQL += chColumn[ m_ordercolumn ];
	csSQL += chOrder[ m_disporder ];
	var = csSQL;
	
	if( m_pRecordset->State )
		m_pRecordset->Close();
	
	try
	{
		m_pRecordset->Open( var,   
			theApp.m_pConnection.GetInterfacePtr(),	 // Get the Ptr of connect lib
			adOpenDynamic,
			adLockOptimistic,
			adCmdText);
	}
	catch(_com_error *e)
	{
		AfxMessageBox(e->ErrorMessage());
	}
}

//
//------------------------------------------------------------
int CFinanceView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CListEditView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// this code only works for a report-mode list view
	ASSERT( GetStyle() & LVS_REPORT );
	
	// Gain a reference to the list control itself
	CListCtrl&		InnerLst = GetListCtrl();
	CHeaderCtrl*	pHeadCtrl = InnerLst.GetHeaderCtrl();
	
	ASSERT( pHeadCtrl );
	
	VERIFY( m_FlatHeader.SubclassWindow( pHeadCtrl->GetSafeHwnd() ) );
	
	return 0;
}

//
//------------------------------------------------------------
void CFinanceView::OnRefresh() 
{
	_variant_t	var;
	LONG		lAbsidx = -1;
	
	
	// <> record "Index" for sync 
	if( m_iLstCurSel >= 0 ) 
	{
		if( m_pRecordset->State )
		{
			var = m_pRecordset->GetCollect("Index");	// LONG
			if(var.vt != VT_NULL)
				lAbsidx = (LONG)(var);	// !!! need check this convertion method !!!
		}
	}
	
	// <> open Account by condition
	OpenAccount();
	
	// <> Fill listctrl content
	ShowAccountRec( lAbsidx );

	// <> Update Count info status bar 
	CHAR		chTmp[30] = { 0 };
	//	  Get pointer to status bar .
	CStatusBar *pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
	
	sprintf( chTmp, " ListView records : %d  ", GetListCtrl().GetItemCount() );
	pStatusBar->SetPaneText( 2, chTmp );
}

//
//------------------------------------------------------------
void CFinanceView::OnAddnew() 
{
	CDlgAddNew dlg;
	
	dlg.DoModal();
	
	OnRefresh();
}

//
//------------------------------------------------------------
void CFinanceView::OnModify() 
{
	CListCtrl&		InnerLst = GetListCtrl();
	POSITION		pos = InnerLst.GetFirstSelectedItemPosition();
	
	
	m_iLstCurSel = InnerLst.GetNextSelectedItem(pos);  // Get item index
	if( m_iLstCurSel >= 0 )
	{
		CDlgModify	dlg;
		_variant_t	var;
		LONG		lAbsidx;
		
		// get abs position based on current openAccount condition
		if( !m_pRecordset->State )
			OpenAccount();
		
		m_pRecordset->MoveFirst();
		m_pRecordset->Move( long(m_iLstCurSel) );
		
		var = m_pRecordset->GetCollect("Index");	// LONG
		if(var.vt != VT_NULL)
			lAbsidx = (LONG)(var);	// !!! need check this convertion method !!!
		
		dlg.SetSelIndex( lAbsidx );
		
		if( dlg.DoModal() == IDOK )	
		{
			OnRefresh(); // refresh

			// <> Refresh Search View
			CSearchView		*pView = NULL;
			CFinanceDoc		*pDoc=(CFinanceDoc*)GetDocument();
			
			if( pDoc )
				pView=(CSearchView*)pDoc->GetView(RUNTIME_CLASS(CSearchView));
			
			if( pView )
				pView->RefreshSearchView();
		}
	}
}

//
//------------------------------------------------------------
void CFinanceView::OnUpdateModify(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( (m_iLstCurSel >= 0) );
}

//
//------------------------------------------------------------
void CFinanceView::OnDeleone() 
{
	CListCtrl&		InnerLst = GetListCtrl();
	_variant_t		var;
	CString			csInfo = "( ";
	CString			csTmp;
	INT				iCount = InnerLst.GetItemCount();
	
	
	if( m_iLstCurSel < 0 || 
		m_iLstCurSel >= iCount ) 
		return ;
	
	var = m_pRecordset->GetCollect("Date");		// data/time	
	if(var.vt != VT_NULL)
		csTmp = (LPCSTR)_bstr_t(var);
	csInfo += csTmp;
	csInfo += ", ";
	
	var = m_pRecordset->GetCollect("Amount");	// nummer
	if(var.vt != VT_NULL)
		csTmp = (LPCSTR)_bstr_t(var);
	csInfo += csTmp;
	csInfo += ", ";
	
	var = m_pRecordset->GetCollect("Purpose");	// txt
	if(var.vt != VT_NULL)
		csTmp = (LPCSTR)_bstr_t(var);
	csInfo += csTmp;
	csInfo += " )\n";
	csInfo +="You will delete this record.\n  Are you sure?";
	
	if( MessageBox( csInfo, "Remind", MB_ICONQUESTION|MB_YESNO ) != IDYES ) 
	{
		return ;
	}
	
	// <> Extend for Bank
	var = m_pRecordset->GetCollect("FlowClass");	// txt
	if(var.vt != VT_NULL)
		csTmp = (LPCSTR)_bstr_t(var);

	if( csTmp == "Bank" ) 
	{
		LONG	lItemIdx;

		if( m_pBankbookset->State )
			m_pBankbookset->Close();

		// <> open Bankbook by "AccountIdx"
		var = m_pRecordset->GetCollect("Index");	// LONG
		if(var.vt != VT_NULL)
			lItemIdx = (LONG)(var);	// !!! need check this convertion method !!!
		csInfo.Format( _T("SELECT * FROM Bankbook WHERE AccountIdx=%ld"), lItemIdx );
		var = csInfo;
		try
		{
			m_pBankbookset->Open( var,   
				theApp.m_pConnection.GetInterfacePtr(),	 // Get the Ptr of connect lib
				adOpenDynamic,
				adLockOptimistic,
				adCmdText);
		}
		catch(_com_error *e)
		{
			AfxMessageBox(e->ErrorMessage());
		}

		// <> Dele record in table( Bankbook )
		try
		{
			if( !m_pBankbookset->BOF )
			{
				m_pBankbookset->Delete( adAffectCurrent );
				m_pBankbookset->Update();
			}
			// else AfxMessageBox("Table is NULL");
		}
		catch(_com_error *e)
		{
			AfxMessageBox(e->ErrorMessage());
		}
	}


	try
	{
		m_pRecordset->Delete( adAffectCurrent );
		m_pRecordset->Update();
	}
	catch(_com_error *e)
	{
		AfxMessageBox(e->ErrorMessage());
	}
	// After Delete(), before Move(), the deleted position will be remain !
	
	// determine the m_iLstCurSel after delete()
	if( m_iLstCurSel == iCount - 1 )	// last, must be --
	{
		InnerLst.DeleteItem( m_iLstCurSel );
		m_iLstCurSel--;
	}
	else
	{
		InnerLst.DeleteItem( m_iLstCurSel );
		// m_iLstCurSel remain current value
	}
	
	// <> synchronize the table( Account )
	if( m_iLstCurSel >= 0 ) 
	{
		InnerLst.SetItemState( m_iLstCurSel, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED );
		
		m_pRecordset->MoveFirst();
		m_pRecordset->Move( long(m_iLstCurSel) );
	}

	// <> Update Count info status bar 
	CHAR		chTmp[30] = { 0 };
	//	  Get pointer to status bar .
	CStatusBar *pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
	
	sprintf( chTmp, " ListView records : %d  ", InnerLst.GetItemCount() );
	pStatusBar->SetPaneText( 2, chTmp );
	
	//OnRefresh(); // Don't need refresh when delete, optimize the performance !
}

//
//------------------------------------------------------------
void CFinanceView::OnUpdateDeleone(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( (m_iLstCurSel >= 0) );
}


// 
// order is ^ after first click
// ^ is a->z, 2005/01/01 -> 2005/07/01
// pNMListView->iSubItem will not be changed postion after user drag head column
//-------------------------------------------------------------------------------
void CFinanceView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW*	pNMListView = (NM_LISTVIEW*)pNMHDR;
	BOOL			bSortAscending;
	// map List column order to ORDERCOLUMN define
	ORDERCOLUMN		iSQLOrder[ACCOUNT_COLUMNS] ={	// listctrl  
									date,			// 0
									amount,			// 1
									purpose,		// 2
									flowclass,		// 3
									owner,			// 4
									comment			// 5
								};

	
	// If clicked on already sorted column, reverse sort order
	if(pNMListView->iSubItem == m_FlatHeader.GetSortColumn(&bSortAscending))
		bSortAscending = !bSortAscending;
	else
        bSortAscending = TRUE;
	
	m_FlatHeader.SetSortColumn(pNMListView->iSubItem, bSortAscending);
	
	// Do some sort of sorting...
	m_ordercolumn = iSQLOrder[ pNMListView->iSubItem ];
	m_disporder = ( bSortAscending ) ? asc : desc;
	
	// <> Refresh
	OnRefresh();
	
	// Note!! m_iLstCurSel will be -1 after ShowAccountRec(), 
	// even if m_iLstCurSel be assigned a valid value before.
	
	*pResult = 0;
}


// 
//--------------------------------------------------------------
void CFinanceView::OnClickList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CListCtrl&	InnerLst = GetListCtrl();
	POSITION	pos = InnerLst.GetFirstSelectedItemPosition();
	
	
	m_iLstCurSel = InnerLst.GetNextSelectedItem(pos);  // Get item index

	if( m_iLstCurSel >= 0 )
	{
		// get abs position based on current openAccount condition
		if( !m_pRecordset->State )
			OpenAccount();

		// set current record, for delete
		m_pRecordset->MoveFirst();
		m_pRecordset->Move( long(m_iLstCurSel) );
	}

	*pResult = 0;
}


// 
//--------------------------------------------------------------
void CFinanceView::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// Modify
	OnModify();

	*pResult = 0;
}


// 
//--------------------------------------------------------------
void CFinanceView::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CPoint pt;
	::GetCursorPos(&pt);

	CListCtrl&		InnerLst = GetListCtrl();
	POSITION		pos = InnerLst.GetFirstSelectedItemPosition();
	
	
	m_iLstCurSel = InnerLst.GetNextSelectedItem(pos);  // Get item index
	
	if( m_iLstCurSel >= 0 )
	{
		// get abs position based on current openAccount condition
		if( !m_pRecordset->State )
			OpenAccount();
		
		// set current record, for delete
		m_pRecordset->MoveFirst();
		m_pRecordset->Move( long(m_iLstCurSel) );
	}
	

	CMenu menu;
	menu.LoadMenu(IDR_RCK_LIST);
	CMenu* pMenu=menu.GetSubMenu(0);
	pMenu->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this,NULL);
	
	*pResult = 0;  
}

// 
//InnerLst.SetSelectionMark( iMarkItem );
//m_iLstCurSel = InnerLst.GetSelectionMark(); // if iMark == count of item ( > max index ), GetSelectionMark() will return the MAX index// if iMark == count of item ( > max index ), GetSelectionMark() will return the MAX index
//--------------------------------------------------------------
void CFinanceView::OnKeyDownList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NMLVKEYDOWN*	pnkd = (NMLVKEYDOWN*)pNMHDR;
	CListCtrl&		InnerLst = GetListCtrl();
	INT				iCount = InnerLst.GetItemCount();
	
	
	if( iCount > 0 ) 
	{
		switch( pnkd->wVKey ) 
		{
		case VK_DOWN:
			if( m_iLstCurSel < 0 )
				m_iLstCurSel = 0;
			else if( m_iLstCurSel >= iCount - 1 ) 
				m_iLstCurSel = iCount - 1;
			else
				m_iLstCurSel++;
			break ;
			
		case VK_UP:
			if( m_iLstCurSel > 0 )
				m_iLstCurSel--;
			else
				m_iLstCurSel = 0;
			break ;
			
		case VK_DELETE:
			OnDeleone();
			*pResult = 0;
			return ;
			
		case VK_INSERT:
			OnAddnew();
			*pResult = 0;
			return ;
			
		case VK_RETURN:
			OnModify();
			*pResult = 0;
			return ;
			
		case VK_F5:
			OnRefresh();
			*pResult = 0;
			return ;
			
		default :
			break ;
		}
		
		if( m_iLstCurSel >= 0 && m_iLstCurSel < iCount )
		{
			// get abs position based on current openAccount condition
			if( !m_pRecordset->State )
				OpenAccount();
			
			// set current record, for delete
			m_pRecordset->MoveFirst();
			m_pRecordset->Move( long(m_iLstCurSel) );
		}
		else
		{
			TRACE( "KAO !" );
		}
	}
	
	*pResult = 0;
}


//
//------------------------------------------------------------
void CFinanceView::OnSetup() 
{
	CPropertySheet	propsheet( "Setup" );
	CPageDateRange	CDateRange;
	CPageLoginInfo	CLoginInfo;
	CPageBakRestore	CBakResotre;
	
	
	propsheet.AddPage( &CDateRange );
	propsheet.AddPage( &CLoginInfo );
	propsheet.AddPage( &CBakResotre );
	
	if( propsheet.DoModal() == IDOK ) 
	{
		OnRefresh();
	}
}

//
// For Other View invoke
//------------------------------------------------------------
void CFinanceView::RefreshListView()
{
	OnRefresh();
}

//
//------------------------------------------------------------
void CFinanceView::OnSearch() 
{
	CDlgSearch		dlg;
	
	
	if( dlg.DoModal() == IDOK ) 
	{
		CSearchView		*pView = NULL;
		CFinanceDoc		*pDoc=(CFinanceDoc*)GetDocument();
		
		if( pDoc )
			pView=(CSearchView*)pDoc->GetView(RUNTIME_CLASS(CSearchView));
		
		if( pView )
			pView->RefreshSearchView();
	}
}

// 
// For refresh status bar immediately, so do use it
//------------------------------------------------------------
//DEL void CFinanceView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
//DEL {
//DEL 	if( NULL!=m_pRecordset && bActivate ) 
//DEL 	{
//DEL 		OnRefresh();
//DEL 	}
//DEL 	
//DEL 	CListEditView::OnActivateView(bActivate, pActivateView, pDeactiveView);
//DEL }

